[アップデート] Amazon Bedrock Agents, Flows, Knowledge bases で Latency-optimized inference がプレビューでサポートされました

[アップデート] Amazon Bedrock Agents, Flows, Knowledge bases で Latency-optimized inference がプレビューでサポートされました

Clock Icon2024.12.24

こんにちは!AWS 事業本部コンサルティング部のたかくに(@takakuni_)です。

Amazon Bedrock Agents, Flows, Knowledge bases で Latency-optimized inference がサポートされました。

https://aws.amazon.com/about-aws/whats-new/2024/12/amazon-bedrock-agents-flows-knowledge-optimized-models/

すでにすごい速度でブログが書かれていますね。素晴らしい。

https://dev.classmethod.jp/articles/bedrock-latency-optimized-new-support/

私も書きたくなったので試してみました。

Latency-optimized inference

Latency-optimized inference は re:Invent 2024 にパブリックプレビューで登場した機能です。

推論に Trainium 2 の利用やソフトウェアの最適化を行い、従来の推論よりも精度を損なうことなくレイテンシの低い応答が見込めるオプションです。

re:Invent 2024 では従来の Haiku 3.5 と比べて 60% 推論スピードが早くなったと紹介されています。

2024-12-24 at 08.39.33-AWS reInvent 2024 - Monday Night Live with Peter DeSantis - YouTube@2x.png

https://youtu.be/vx36tyJ47ps?si=o_H1s8rZOzb4AmZM

機能

アップデートのタイトルだと、Amazon Bedrock Agents, Flows, Knowledge bases のすべての機能でサポートしたように見えますが、調べてみたところ以下のサポートを指しているようです。

一部予想が含まれますが、エージェント部分は注意が必要だと思います。

  • Amazon Bedrock Agents
    • invoke_inline_agent をサポート
    • invoke_agent は未サポート(予想)
  • Flows
    • 不明
  • Knowledge bases
    • RetreiveAndGenerate, RetrieveAndGenerateStream でサポート(問題なく使える)
    • クエリ分割や基礎モデルを使ったパース処理はそもそも 3.5 Haiku 未サポート

モデル

利用可能なモデルは現在、 Anthropic's Claude 3.5 Haiku model と Meta's Llama 3.1 405B, 70B models です。

The optimized versions of Anthropic's Claude 3.5 Haiku model and Meta's Llama 3.1 405B and 70B models offer significantly reduced latency without compromising accuracy.

また、特徴的なのはクロスリージョン推論であることです。

レイテンシ最適化推論はオレゴンリージョンを経由して、クロスリージョン推論される旨が記載されています。

Latency optimized inference is available for Meta’s Llama 3.1 70B and 405B, as well as Anthropic’s Claude 3.5 Haiku in the US East (Ohio) Region via cross-region inference. For more information about pricing, visit the pricing page.

https://docs.aws.amazon.com/bedrock/latest/userguide/latency-optimized-inference.html

料金

続いて料金です。

レイテンシを高める分、 25% ほど料金高めに設定されています。

モデル名 Price per 1,000 input tokens Price per 1,000 output tokens
Claude 3.5 Haiku $0.001 $0.005
Llama 3.1 Instruct (70B) (w/ latency optimized inference) $0.0009 $0.0009
Llama 3.1 Instruct (405B) (w/ latency optimized inference) $0.003 $0.003

最新情報は料金表をご覧ください。

https://aws.amazon.com/bedrock/pricing/?nc1=h_ls

ログ

CloudTrail のデータイベントまたは Amazon Bedrock のログに最適化されたノードで推論されたのか、従来のノードで推論されたのか記録されるそうです。

レイテンシ最適化の効果測定の指標として、

Once you reach the usage quota for latency optimization for a model, we will attempt to serve the request with Standard latency. In such cases, the request will be charged at Standard latency rates. The latency configuration for a served request is visible in API response and AWS CloudTrail logs. You can also view metrics for latency optimized requests in Amazon CloudWatch logs under "model-id+latency-optimized".

https://docs.aws.amazon.com/bedrock/latest/userguide/latency-optimized-inference.html

やってみた

それでは簡単にですが Agents, Knowledge bases を使ってレイテンシ最適化モデルを使ってみようと思います。

モデルは一律 us.anthropic.claude-3-5-haiku-20241022-v1:0 を利用します。

今回利用したコードは以下に格納されています。バージニア、オハイオ、オレゴンの 3 リージョンでエージェント、ナレッジベースを作成するコードになります。

ブログを書き切ってから気がついたのですが、少しオーバースペック気味かも知れせん。

https://github.com/takakuni-classmethod/genai-blog/tree/main/bedrock_latency_optimized_inference

Agents

エージェントから確認を行います。まずはオハイオリージョンの invoke_agent.py から試してみます。

あえて、レイテンシ最適化オプションを指定しない状態で実行します。

invoke_agent.py
import boto3
from uuid import uuid4

AWS_ACCOUNT_ID = '123456789012'  # AWS アカウント ID を記載

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載
AGENT_ID = 'F48G7VBRQ5'  # エージェント ID を記載
AGENT_ALIAS_ID = 'T3HCO5U8NN'  # エージェントエイリアス ID を記載

session_id = str(uuid4())

input_text = '桃太郎はどこで生まれましたか?'
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime', region_name=REGION)

# Agentの実行
response = bedrock_agent_runtime.invoke_agent(
    inputText=input_text,
    agentId=AGENT_ID,
    agentAliasId=AGENT_ALIAS_ID,
    sessionId=session_id,
    enableTrace=False,
)

# Agent実行結果の取得
event_stream = response['completion']
for event in event_stream:
    if 'chunk' in event:
        data = event['chunk']['bytes'].decode('utf-8')
        print(data)

今回の検証にあまり関係ないですが、回答は正しく返ってきています。

takakuni app % python agent.py
桃太郎は、おじいさんとおばあさんが川で見つけた桃の中から生まれました。おばあさんが桃を抱いていると、突然桃が割れて、元気な赤ちゃんが生まれたのです。

推論先リージョン(inferenceRegion)は us-west-2(オレゴン)であることがわかります。

no_specify_latency_ohio.json
{
	"schemaType": "ModelInvocationLog",
	"schemaVersion": "1.0",
	"timestamp": "2024-12-24T07:24:25Z",
	"accountId": "123456789012",
	"identity": {
		"arn": "arn:aws:sts::123456789012:assumed-role/ltncy-optmzd-infrnc-agents-role-us-east-2/BedrockAgents-F48G7VBRQ5-983fe347-6dbb-4d8a-8779-0a36cc718b06"
	},
	"region": "us-east-2",
	"requestId": "8c0a0eff-8174-453b-9ffb-42f21431a842",
	"operation": "InvokeModel",
	"modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
	"input": {
		"inputContentType": "application/json",
		"inputBodyJson": {
			"anthropic_version": "bedrock-2023-05-31",
			"system": "省略",
			"messages": [
				{
					"content": [
						{
							"type": "text",
							"text": "桃太郎はどこで生まれましたか?"
						}
					],
					"role": "user"
				}
			],
			"top_k": 250,
			"top_p": 1,
			"temperature": 0,
			"stop_sequences": ["\n\nHuman:"],
			"max_tokens": 2048
		},
		"inputTokenCount": 1662
	},
	"output": {
		"outputContentType": "application/json",
		"outputBodyJson": {
			"id": "msg_bdrk_01UHTNZPe3Xe1Z18Wc3YfTBn",
			"type": "message",
			"role": "assistant",
			"model": "claude-3-5-haiku-20241022",
			"content": [
				{
					"type": "text",
					"text": "<answer>\n<answer_part>\n<text>\n桃太郎は、おじいさんとおばあさんが川で見つけた桃の中から生まれました。おばあさんが桃を抱いていると、突然桃が割れて、元気な赤ちゃんが生まれたのです。\n</text>\n<sources>\n<source>5</source>\n</sources>\n</answer_part>\n</answer>"
				}
			],
			"stop_reason": "end_turn",
			"stop_sequence": null,
			"usage": {
				"input_tokens": 1662,
				"output_tokens": 124
			}
		},
		"outputTokenCount": 124
	},
	"inferenceRegion": "us-west-2"
}

続いてレイテンシ最適化オプションを Standard で指定し実行します。

invoke_agent.py

import boto3
from uuid import uuid4

AWS_ACCOUNT_ID = '123456789012'  # AWS アカウント ID を記載

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載
AGENT_ID = 'F48G7VBRQ5'  # エージェント ID を記載
AGENT_ALIAS_ID = 'T3HCO5U8NN'  # エージェントエイリアス ID を記載

session_id = str(uuid4())

input_text = '桃太郎はどこで生まれましたか?'
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime', region_name=REGION)
+ latency = 'standard'

# Agentの実行
response = bedrock_agent_runtime.invoke_agent(
    inputText=input_text,
    agentId=AGENT_ID,
    agentAliasId=AGENT_ALIAS_ID,
    sessionId=session_id,
    enableTrace=False,
+    bedrockModelConfigurations={
+        'performanceConfig': {
+            'latency': latency
+        }
+    },
)

# Agent実行結果の取得
event_stream = response['completion']
for event in event_stream:
    if 'chunk' in event:
        data = event['chunk']['bytes'].decode('utf-8')
        print(data)

同じく推論先リージョン(inferenceRegion)が us-west-2(オレゴン)であることがわかります。

specify_latency_ohio.json
{
	"schemaType": "ModelInvocationLog",
	"schemaVersion": "1.0",
	"timestamp": "2024-12-24T07:30:03Z",
	"accountId": "123456789012",
	"identity": {
		"arn": "arn:aws:sts::123456789012:assumed-role/ltncy-optmzd-infrnc-agents-role-us-east-2/BedrockAgents-F48G7VBRQ5-e8ddc2ea-9b4e-4115-9d40-3754d00b7e4b"
	},
	"region": "us-east-2",
	"requestId": "5128c752-1ef9-492c-a672-cdfe8b1b0e7b",
	"operation": "InvokeModel",
	"modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
	"input": {
		"inputContentType": "application/json",
		"inputBodyJson": {
			"anthropic_version": "bedrock-2023-05-31",
			"system": "省略",
			"messages": [
				{
					"content": [
						{
							"type": "text",
							"text": "桃太郎はどこで生まれましたか?"
						}
					],
					"role": "user"
				}
			],
			"top_k": 250,
			"top_p": 1,
			"temperature": 0,
			"stop_sequences": ["\n\nHuman:"],
			"max_tokens": 2048
		},
		"inputTokenCount": 1662
	},
	"output": {
		"outputContentType": "application/json",
		"outputBodyJson": {
			"id": "msg_bdrk_011LJmgTWbQhnWVFp9mfr9pY",
			"type": "message",
			"role": "assistant",
			"model": "claude-3-5-haiku-20241022",
			"content": [
				{
					"type": "text",
					"text": "<answer>\n<answer_part>\n<text>\n桃太郎は、おじいさんとおばあさんが川で見つけた桃の中から生まれました。おばあさんが桃を抱いていると、突然桃が割れて、元気な赤ちゃんが生まれたのです。\n</text>\n<sources>\n<source>5</source>\n</sources>\n</answer_part>\n</answer>"
				}
			],
			"stop_reason": "end_turn",
			"stop_sequence": null,
			"usage": {
				"input_tokens": 1662,
				"output_tokens": 124
			}
		},
		"outputTokenCount": 124
	},
	"inferenceRegion": "us-west-2"
}

それではお待ちかねの latency を optimized に変更します。

invoke_agent.py
import boto3
from uuid import uuid4

AWS_ACCOUNT_ID = '123456789012'  # AWS アカウント ID を記載

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載
AGENT_ID = 'F48G7VBRQ5'  # エージェント ID を記載
AGENT_ALIAS_ID = 'T3HCO5U8NN'  # エージェントエイリアス ID を記載

session_id = str(uuid4())

input_text = '桃太郎はどこで生まれましたか?'
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime', region_name=REGION)
- latency = 'standard'
+ latency = 'optimized'

# Agentの実行
response = bedrock_agent_runtime.invoke_agent(
    inputText=input_text,
    agentId=AGENT_ID,
    agentAliasId=AGENT_ALIAS_ID,
    sessionId=session_id,
    enableTrace=False,
    bedrockModelConfigurations={
        'performanceConfig': {
            'latency': latency
        }
    },
)

# Agent実行結果の取得
event_stream = response['completion']
for event in event_stream:
    if 'chunk' in event:
        data = event['chunk']['bytes'].decode('utf-8')
        print(data)

結果が返ってきました!が、推論先リージョンは us-west-2 のままですね。

specify_latency_oregon.json
{
	"schemaType": "ModelInvocationLog",
	"schemaVersion": "1.0",
	"timestamp": "2024-12-24T07:33:27Z",
	"accountId": "123456789012",
	"identity": {
		"arn": "arn:aws:sts::123456789012:assumed-role/ltncy-optmzd-infrnc-agents-role-us-east-2/BedrockAgents-F48G7VBRQ5-714d9ed9-47e5-460b-98e1-92af072cf650"
	},
	"region": "us-east-2",
	"requestId": "49f43a71-1283-4daa-81e4-466bc6b14f95",
	"operation": "InvokeModel",
	"modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
	"input": {
		"inputContentType": "application/json",
		"inputBodyJson": {
			"anthropic_version": "bedrock-2023-05-31",
			"system": "省略",
			"messages": [
				{
					"content": [
						{
							"type": "text",
							"text": "桃太郎はどこで生まれましたか?"
						}
					],
					"role": "user"
				}
			],
			"top_k": 250,
			"top_p": 1,
			"temperature": 0,
			"stop_sequences": ["\n\nHuman:"],
			"max_tokens": 2048
		},
		"inputTokenCount": 1662
	},
	"output": {
		"outputContentType": "application/json",
		"outputBodyJson": {
			"id": "msg_bdrk_016DwAsr42qYJKHqqmWmk8Zv",
			"type": "message",
			"role": "assistant",
			"model": "claude-3-5-haiku-20241022",
			"content": [
				{
					"type": "text",
					"text": "<answer>\n<answer_part>\n<text>\n桃太郎は、おじいさんとおばあさんが川で見つけた桃の中から生まれました。おばあさんが桃を抱いていると、突然桃が割れて、元気な赤ちゃんが生まれたのです。\n</text>\n<sources>\n<source>5</source>\n</sources>\n</answer_part>\n</answer>"
				}
			],
			"stop_reason": "end_turn",
			"stop_sequence": null,
			"usage": {
				"input_tokens": 1662,
				"output_tokens": 124
			}
		},
		"outputTokenCount": 124
	},
	"inferenceRegion": "us-west-2"
}

おそらくここで、リージョン変えてみるとどうなる?が浮かぶと思います。やってみましょう。

invoke_agent.py
import boto3
from uuid import uuid4

AWS_ACCOUNT_ID = '123456789012'  # AWS アカウント ID を記載

- ################################################
- # Ohio
- ################################################
- REGION = 'us-east-2'  # リージョンを記載
- AGENT_ID = 'F48G7VBRQ5'  # エージェント ID を記載
- AGENT_ALIAS_ID = 'T3HCO5U8NN'  # エージェントエイリアス ID を記載
+ ################################################
+ # Oregon
+ ################################################
+ REGION = 'us-west-2'  # リージョンを記載
+ AGENT_ID = '4QTBERXYCV'  # エージェント ID を記載
+ AGENT_ALIAS_ID = '4KBDMYC2KZ'  # エージェントエイリアス ID を記載

session_id = str(uuid4())

input_text = '桃太郎はどこで生まれましたか?'
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime', region_name=REGION)
latency = 'optimized'

# Agentの実行
response = bedrock_agent_runtime.invoke_agent(
    inputText=input_text,
    agentId=AGENT_ID,
    agentAliasId=AGENT_ALIAS_ID,
    sessionId=session_id,
    enableTrace=False,
    bedrockModelConfigurations={
        'performanceConfig': {
            'latency': latency
        }
    },
)

# Agent実行結果の取得
event_stream = response['completion']
for event in event_stream:
    if 'chunk' in event:
        data = event['chunk']['bytes'].decode('utf-8')
        print(data)

残念ながら状況変わらずでして、推論先リージョンはオレゴンのままになります。

この状況から invoke_agent はレイテンシ最適化オプションの対象外であることが予想されます。

specify_latency_oregon.json
{
    "schemaType": "ModelInvocationLog",
    "schemaVersion": "1.0",
    "timestamp": "2024-12-24T07:35:36Z",
    "accountId": "123456789012",
    "identity": {
        "arn": "arn:aws:sts::123456789012:assumed-role/ltncy-optmzd-infrnc-agents-role-us-west-2/BedrockAgents-4QTBERXYCV-84bfdae7-2780-45d3-afe3-75a51cf0cf52"
    },
    "region": "us-west-2",
    "requestId": "6b2fa1e6-4cda-4dc1-9ed2-e63f8e08f670",
    "operation": "InvokeModel",
    "modelId": "arn:aws:bedrock:us-west-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
    "input": {
        "inputContentType": "application/json",
        "inputBodyJson": {
            "anthropic_version": "bedrock-2023-05-31",
            "system": "省略",
            "messages": [
                {
                    "content": [
                        {
                            "type": "text",
                            "text": "桃太郎はどこで生まれましたか?"
                        }
                    ],
                    "role": "user"
                }
            ],
            "max_tokens": 2048,
            "top_k": 250,
            "top_p": 1,
            "temperature": 0,
            "stop_sequences": [
                "\n\nHuman:"
            ]
        },
        "inputTokenCount": 1662
    },
    "output": {
        "outputContentType": "application/json",
        "outputBodyJson": {
            "id": "msg_bdrk_01EqqvjGB8h2qhF8VsYiMRbe",
            "type": "message",
            "role": "assistant",
            "model": "claude-3-5-haiku-20241022",
            "content": [
                {
                    "type": "text",
                    "text": "<answer>\n<answer_part>\n<text>\n桃太郎は、おじいさんとおばあさんが川で見つけた桃の中から生まれました。おばあさんが桃を抱いていると、突然桃が割れて、元気な赤ちゃんが生まれたのです。\n</text>\n<sources>\n<source>5</source>\n</sources>\n</answer_part>\n</answer>"
                }
            ],
            "stop_reason": "end_turn",
            "stop_sequence": null,
            "usage": {
                "input_tokens": 1662,
                "output_tokens": 124
            }
        },
        "outputTokenCount": 124
    },
    "inferenceRegion": "us-west-2"
}

Inline Agents

話が戻りまして、インラインエージェントを試してみます。まずはいつも通りレイテンシ最適化オプションなしで実行します。

inline_agent_tmp.py
import boto3
import time
from uuid import uuid4
from pprint import pprint

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載

session_id = str(uuid4())
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime', region_name=REGION)
model_id = "us.anthropic.claude-3-5-haiku-20241022-v1:0"

inputText = """
桃太郎はどこで生まれましたか?
"""

response = bedrock_agent_runtime.invoke_inline_agent(
    sessionId=session_id,
    inputText=inputText,
    endSession=False,
    enableTrace=True,
    foundationModel=model_id,
    instruction="あなたは物知りです。ユーザから入力された質問に対して、己の頭のみ気合いで回答します。",
)

# Agent実行結果の取得
event_stream = response['completion']
for event in event_stream:
    if 'chunk' in event:
        data = event['chunk']['bytes'].decode('utf-8')
        print(data)

とくに変わりなく推論先リージョン(inferenceRegion)はオレゴンのままですね。

no_specify_latency_ohio.json
{
    "schemaType": "ModelInvocationLog",
    "schemaVersion": "1.0",
    "timestamp": "2024-12-24T07:42:40Z",
    "accountId": "123456789012",
    "identity": {
        "arn": "arn:aws:sts::123456789012:assumed-role/takakuni/botocore-session-1735025322"
    },
    "region": "us-east-2",
    "requestId": "1de3a42b-d794-4444-b3de-1710f250cce3",
    "operation": "InvokeModel",
    "modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
    "input": {
        "inputContentType": "application/json",
        "inputBodyJson": {
            "anthropic_version": "bedrock-2023-05-31",
            "system": "省略",
            "messages": [
                {
                    "content": [
                        {
                            "type": "text",
                            "text": "桃太郎はどこで生まれましたか?"
                        }
                    ],
                    "role": "user"
                }
            ],
            "top_k": 250,
            "tools": [],
            "max_tokens": 2048,
            "top_p": 1,
            "temperature": 0,
            "stop_sequences": [
                "</invoke>",
                "</answer>",
                "</error>"
            ]
        },
        "inputTokenCount": 235
    },
    "output": {
        "outputContentType": "application/json",
        "outputBodyJson": {
            "id": "msg_bdrk_019KqkVAUBvyHkoHRvDCB3yP",
            "type": "message",
            "role": "assistant",
            "model": "claude-3-5-haiku-20241022",
            "content": [
                {
                    "type": "text",
                    "text": "<thinking>\n桃太郎の伝統的な昔話について考えてみます。桃太郎の origin(起源)について、よく知られている民話の内容を思い出します。\n</thinking>\n\n<answer>\n桃太郎は、川のなかを流れてきた大きな桃の中で生まれたと言われています。ある老夫婦が川で桃を見つけ、その桃を割ると、中から元気な男の子が生まれました。これが桃太郎の誕生の物語です。具体的な場所は、日本の田舎の川のほとりとされています。\n"
                }
            ],
            "stop_reason": "stop_sequence",
            "stop_sequence": "</answer>",
            "usage": {
                "input_tokens": 235,
                "output_tokens": 182
            }
        },
        "outputTokenCount": 182
    },
    "inferenceRegion": "us-west-2"
}

続いてレイテンシ最適化オプションをデフォルトで指定した場合の挙動を確認します。

inline_agent.py
import boto3
import time
from uuid import uuid4
from pprint import pprint

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載

session_id = str(uuid4())
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime', region_name=REGION)
model_id = "us.anthropic.claude-3-5-haiku-20241022-v1:0"

inputText = """
桃太郎はどこで生まれましたか?
"""
+ latency = 'standard'

response = bedrock_agent_runtime.invoke_inline_agent(
    sessionId=session_id,
    inputText=inputText,
    endSession=False,
    enableTrace=True,
    foundationModel=model_id,
    instruction="あなたは物知りです。ユーザから入力された質問に対して、己の頭のみ気合いで回答します。",
+    bedrockModelConfigurations={'performanceConfig': {'latency': latency}},
)

# Agent実行結果の取得
event_stream = response['completion']
for event in event_stream:
    if 'chunk' in event:
        data = event['chunk']['bytes'].decode('utf-8')
        print(data)

おっと、先ほどと変わり output.performanceConfig.latency が登場してきました。推論先リージョンは変わらずオレゴンですね。

specify_latency_ohio.json
{
	"schemaType": "ModelInvocationLog",
	"schemaVersion": "1.0",
	"timestamp": "2024-12-24T07:47:00Z",
	"accountId": "123456789012",
	"identity": {
		"arn": "arn:aws:sts::123456789012:assumed-role/takakuni/botocore-session-1735025322"
	},
	"region": "us-east-2",
	"requestId": "5e13ad29-791d-4a10-995e-61616d9d7db3",
	"operation": "InvokeModel",
	"modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
	"input": {
		"inputContentType": "application/json",
		"inputBodyJson": {
			"anthropic_version": "bedrock-2023-05-31",
			"system": "省略",
			"messages": [
				{
					"content": [
						{
							"type": "text",
							"text": "桃太郎はどこで生まれましたか?"
						}
					],
					"role": "user"
				}
			],
			"max_tokens": 2048,
			"top_k": 250,
			"tools": [],
			"top_p": 1,
			"temperature": 0,
			"stop_sequences": ["</invoke>", "</answer>", "</error>"]
		},
		"inputTokenCount": 235
	},
	"output": {
		"outputContentType": "application/json",
		"outputBodyJson": {
			"id": "msg_bdrk_01EnzRgpq4c1SPp9TVFuKFi2",
			"type": "message",
			"role": "assistant",
			"model": "claude-3-5-haiku-20241022",
			"content": [
				{
					"type": "text",
					"text": "<thinking>\n桃太郎の伝統的な昔話について考えてみます。桃太郎の origin(起源)について、よく知られている民話の内容を思い出します。\n</thinking>\n\n<answer>\n桃太郎は、川のなかを流れてきた大きな桃の中で生まれたと言われています。ある老夫婦が川で桃を見つけ、その桃を割ると、中から元気な男の子が生まれました。これが桃太郎の誕生の物語です。具体的な場所は、日本の田舎の川のほとりとされています。\n"
				}
			],
			"stop_reason": "stop_sequence",
			"stop_sequence": "</answer>",
			"usage": {
				"input_tokens": 235,
				"output_tokens": 182
			}
		},
		"outputTokenCount": 182
	},
	"performanceConfig": {
		"latency": "STANDARD"
	},
	"inferenceRegion": "us-west-2"
}

最後に最適化されたオプションを試します。

inline_agent.py
import boto3
import time
from uuid import uuid4
from pprint import pprint

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載

session_id = str(uuid4())
bedrock_agent_runtime = boto3.client('bedrock-agent-runtime', region_name=REGION)
model_id = "us.anthropic.claude-3-5-haiku-20241022-v1:0"

inputText = """
桃太郎はどこで生まれましたか?
"""
- latency = 'standard'
+ latency = 'optimized'

response = bedrock_agent_runtime.invoke_inline_agent(
    sessionId=session_id,
    inputText=inputText,
    endSession=False,
    enableTrace=True,
    foundationModel=model_id,
    instruction="あなたは物知りです。ユーザから入力された質問に対して、己の頭のみ気合いで回答します。",
    bedrockModelConfigurations={'performanceConfig': {'latency': latency}},
)

# Agent実行結果の取得
event_stream = response['completion']
for event in event_stream:
    if 'chunk' in event:
        data = event['chunk']['bytes'].decode('utf-8')
        print(data)

output.performanceConfig.latencyOPTIMIZED になりました。推論先リージョンもオハイオに変わっています。やっと、推論最適化オプションに辿り着けました。

no_specify_latency_ohio.json
{
	"schemaType": "ModelInvocationLog",
	"schemaVersion": "1.0",
	"timestamp": "2024-12-24T07:50:12Z",
	"accountId": "123456789012",
	"identity": {
		"arn": "arn:aws:sts::123456789012:assumed-role/takakuni/botocore-session-1735025322"
	},
	"region": "us-east-2",
	"requestId": "cf693734-8d8d-4791-a0d8-addaf5598397",
	"operation": "InvokeModel",
	"modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
	"input": {
		"inputContentType": "application/json",
		"inputBodyJson": {
			"anthropic_version": "bedrock-2023-05-31",
			"system": "省略",
			"messages": [
				{
					"content": [
						{
							"type": "text",
							"text": "桃太郎はどこで生まれましたか?"
						}
					],
					"role": "user"
				}
			],
			"tools": [],
			"top_k": 250,
			"top_p": 1,
			"temperature": 0,
			"stop_sequences": ["</invoke>", "</answer>", "</error>"],
			"max_tokens": 2048
		},
		"inputTokenCount": 235
	},
	"output": {
		"outputContentType": "application/json",
		"outputBodyJson": {
			"id": "msg_bdrk_01QfsPyTPHm6TYDFwKpXAqXw",
			"type": "message",
			"role": "assistant",
			"model": "claude-3-5-haiku-20241022",
			"content": [
				{
					"type": "text",
					"text": "<thinking>\n桃太郎の伝統的な昔話について考えてみます。桃太郎の origin(起源)について、よく知られている民話の内容を思い出します。\n</thinking>\n\n<answer>\n桃太郎は、川のほとりで老夫婦が洗濯をしていたときに、大きな桃が流れてきて、その桃を割ると中から生まれたと言われています。具体的には、岡山県(桃太郎伝説の発祥地)の川のほとりで、おばあさんが桃を見つけ、それを割ったところから桃太郎が生まれたとされています。\n"
				}
			],
			"stop_reason": "stop_sequence",
			"stop_sequence": "</answer>",
			"usage": {
				"input_tokens": 235,
				"output_tokens": 194
			}
		},
		"outputTokenCount": 194
	},
	"performanceConfig": {
		"latency": "OPTIMIZED"
	},
	"inferenceRegion": "us-east-2"
}

Knowledge bases

最後に Knowledge bases の RetrieveAndGenerate API を試して終わりにしましょう。

いつものようにレイテンシ最適化オプション無しから試してみます。

knowledge_base.py
import boto3

AWS_ACCOUNT_ID = "123456789012"  # AWS アカウント ID を記載

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載
KNOWLEDGEBASE_ID = 'RF0PTTDMZG'  # ナレッジベース ID を記載
bedrock_agent_runtime = boto3.client("bedrock-agent-runtime", region_name=REGION)

prompt = (
    "桃太郎はどこで生まれましたか?"
)

response = bedrock_agent_runtime.retrieve_and_generate(
    input={"text": prompt},
    retrieveAndGenerateConfiguration={
        "type": "KNOWLEDGE_BASE",
        "knowledgeBaseConfiguration": {
            "knowledgeBaseId": KNOWLEDGEBASE_ID,
            "modelArn": f"arn:aws:bedrock:{REGION}:{AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
        },
    },
)
print(response["output"]["text"],flush=False)

推論先リージョンはオレゴンで想定通りです。

ナレッジベースのログの場合に output.outputBodyJson.metrics.latencyMs に推論にかかった時間が起票されるのでいいですよね。エージェント側も対応して欲しいですね。

{
	"schemaType": "ModelInvocationLog",
	"schemaVersion": "1.0",
	"timestamp": "2024-12-24T07:55:45Z",
	"accountId": "123456789012",
	"identity": {
		"arn": "arn:aws:sts::123456789012:assumed-role/takakuni/botocore-session-1735025322"
	},
	"region": "us-east-2",
	"requestId": "8a98e19a-5d2b-473a-9fa2-d8e7563d245d",
	"operation": "Converse",
	"modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
	"input": {
		"inputContentType": "application/json",
		"inputBodyJson": {
			"messages": [
				{
					"role": "user",
					"content": [
						{
							"text": "桃太郎はどこで生まれましたか?"
						}
					]
				}
			],
			"system": [
				{
					"text": "省略"
				}
			],
			"inferenceConfig": {
				"maxTokens": 2048,
				"temperature": 0,
				"topP": 1,
				"stopSequences": ["\nObservation"]
			}
		},
		"inputTokenCount": 1679
	},
	"output": {
		"outputContentType": "application/json",
		"outputBodyJson": {
			"output": {
				"message": {
					"role": "assistant",
					"content": [
						{
							"text": "<answer>\n<answer_part>\n<text>\n桃太郎は桃の中から生まれました。おじいさんとおばあさんが川で桃を見つけ、その桃を割ると、中から元気な赤ちゃんが生まれたのです。おじいさんとおばあさんは驚きながらも喜び、この子を桃の中から生まれたことから「桃太郎」と名付けました。\n</text>\n<sources>\n<source>5</source>\n</sources>\n</answer_part>\n</answer>"
						}
					]
				}
			},
			"stopReason": "end_turn",
			"metrics": {
				"latencyMs": 3438
			},
			"usage": {
				"inputTokens": 1679,
				"outputTokens": 162,
				"totalTokens": 1841
			}
		},
		"outputTokenCount": 162
	},
	"inferenceRegion": "us-west-2"
}

続いてレイテンシ最適化オプションありの Standard を試してみます。

knowledge_base.py
import boto3

AWS_ACCOUNT_ID = "123456789012"  # AWS アカウント ID を記載

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載
KNOWLEDGEBASE_ID = 'RF0PTTDMZG'  # ナレッジベース ID を記載

+ letency = "standard"
bedrock_agent_runtime = boto3.client("bedrock-agent-runtime", region_name=REGION)

prompt = (
    "桃太郎はどこで生まれましたか?"
)

response = bedrock_agent_runtime.retrieve_and_generate(
    input={"text": prompt},
    retrieveAndGenerateConfiguration={
        "type": "KNOWLEDGE_BASE",
        "knowledgeBaseConfiguration": {
+            "generationConfiguration": {
+                "performanceConfig": {
+                    "latency" : letency
+                }
+            },
            "knowledgeBaseId": KNOWLEDGEBASE_ID,
            "modelArn": f"arn:aws:bedrock:{REGION}:{AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
        },
    },
)
print(response["output"]["text"],flush=False)

インラインエージェントと同じように output.performanceConfig.latency が登場してきました。推論先リージョンは変わらずオレゴンです。latencyMs も 4539 と若干の誤差くらいでしょうか。

{
    "schemaType": "ModelInvocationLog",
    "schemaVersion": "1.0",
    "timestamp": "2024-12-24T08:01:57Z",
    "accountId": "123456789012",
    "identity": {
        "arn": "arn:aws:sts::123456789012:assumed-role/takakuni/botocore-session-1735025322"
    },
    "region": "us-east-2",
    "requestId": "da3ed08f-aacb-458f-a186-5eb863be9020",
    "operation": "Converse",
    "modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
    "input": {
        "inputContentType": "application/json",
        "inputBodyJson": {
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {
                            "text": "桃太郎はどこで生まれましたか?"
                        }
                    ]
                }
            ],
            "system": [
                {
                    "text": "省略"
                }
            ],
            "inferenceConfig": {
                "maxTokens": 2048,
                "temperature": 0,
                "topP": 1,
                "stopSequences": [
                    "\nObservation"
                ]
            }
        },
        "inputTokenCount": 1679
    },
    "output": {
        "outputContentType": "application/json",
        "outputBodyJson": {
            "output": {
                "message": {
                    "role": "assistant",
                    "content": [
                        {
                            "text": "<answer>\n<answer_part>\n<text>\n桃太郎は桃の中から生まれました。おじいさんとおばあさんが川で桃を見つけ、その桃を割ると、中から元気な赤ちゃんが生まれたのです。おじいさんとおばあさんは驚きながらも喜び、この子を桃の中から生まれたことから「桃太郎」と名付けました。\n</text>\n<sources>\n<source>5</source>\n</sources>\n</answer_part>\n</answer>"
                        }
                    ]
                }
            },
            "stopReason": "end_turn",
            "metrics": {
                "latencyMs": 4539
            },
            "usage": {
                "inputTokens": 1679,
                "outputTokens": 162,
                "totalTokens": 1841
            }
        },
        "outputTokenCount": 162
    },
    "performanceConfig": {
        "latency": "STANDARD"
    },
    "inferenceRegion": "us-west-2"
}

最後にレイテンシ最適化オプションありの Optimized を試してみます。

knowledge_base.py
import boto3

AWS_ACCOUNT_ID = "123456789012"  # AWS アカウント ID を記載

################################################
# Ohio
################################################
REGION = 'us-east-2'  # リージョンを記載
KNOWLEDGEBASE_ID = 'RF0PTTDMZG'  # ナレッジベース ID を記載

- letency = "standard"
+ letency = "optimized"
bedrock_agent_runtime = boto3.client("bedrock-agent-runtime", region_name=REGION)

prompt = (
    "桃太郎はどこで生まれましたか?"
)

response = bedrock_agent_runtime.retrieve_and_generate(
    input={"text": prompt},
    retrieveAndGenerateConfiguration={
        "type": "KNOWLEDGE_BASE",
        "knowledgeBaseConfiguration": {
            "generationConfiguration": {
                "performanceConfig": {
                    "latency" : letency
                }
            },
            "knowledgeBaseId": KNOWLEDGEBASE_ID,
            "modelArn": f"arn:aws:bedrock:{REGION}:{AWS_ACCOUNT_ID}:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
        },
    },
)
print(response["output"]["text"],flush=False)

想定通り推論先リージョンはオレゴン、レイテンシ最適化オプションも OPTIMIZED になっています。

latencyMs も 1958 と推論速度は半分以下になっていますね。(試したのは 1 回なので試行回数を増やせば最大 60% もあってそうですね)

{
	"schemaType": "ModelInvocationLog",
	"schemaVersion": "1.0",
	"timestamp": "2024-12-24T08:04:40Z",
	"accountId": "123456789012",
	"identity": {
		"arn": "arn:aws:sts::123456789012:assumed-role/takakuni/botocore-session-1735025322"
	},
	"region": "us-east-2",
	"requestId": "65167716-3282-4b84-98d2-4f8e0ea3a78f",
	"operation": "Converse",
	"modelId": "arn:aws:bedrock:us-east-2:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0",
	"input": {
		"inputContentType": "application/json",
		"inputBodyJson": {
			"messages": [
				{
					"role": "user",
					"content": [
						{
							"text": "桃太郎はどこで生まれましたか?"
						}
					]
				}
			],
			"system": [
				{
					"text": "省略"
				}
			],
			"inferenceConfig": {
				"maxTokens": 2048,
				"temperature": 0,
				"topP": 1,
				"stopSequences": ["\nObservation"]
			}
		},
		"inputTokenCount": 1679
	},
	"output": {
		"outputContentType": "application/json",
		"outputBodyJson": {
			"output": {
				"message": {
					"role": "assistant",
					"content": [
						{
							"text": "<answer>\n<answer_part>\n<text>\n桃太郎は桃の中から生まれました。おじいさんとおばあさんが川で桃を見つけ、その桃を割ると、中から元気な赤ちゃんが生まれたのです。生まれた直後から、赤ちゃんは非常に元気で、おばあさんの手をはねのけるほどの強さでした。\n</text>\n<sources>\n<source>5</source>\n</sources>\n</answer_part>\n</answer>"
						}
					]
				}
			},
			"stopReason": "end_turn",
			"metrics": {
				"latencyMs": 1958
			},
			"usage": {
				"inputTokens": 1679,
				"outputTokens": 157,
				"totalTokens": 1836
			}
		},
		"outputTokenCount": 157
	},
	"performanceConfig": {
		"latency": "OPTIMIZED"
	},
	"inferenceRegion": "us-east-2"
}

まとめ

以上、「Amazon Bedrock Agents, Flows, Knowledge bases で Latency-optimized inference がプレビューでサポートされました」でした。

ログにすると対応しているかどうか、推論に発生した時間が非常にわかりやすいですね。

Latency-optimized inference の対応モデルも増えていくことに期待しています。

AWS 事業本部コンサルティング部のたかくに(@takakuni_)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.